/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.section;


import java.util.Iterator;

import org.eclipse.gef.EditPart;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.BehavioralFeature;
import org.eclipse.uml2.uml.BehavioredClassifier;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.StateMachine;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.core.ui.dialogs.OperationTreeSelectionDialog;
import com.cea.papyrus.core.utils.LookForElement;

/**
 * Section in the property views to set the specification of a Behavior.
 * 
 * @author David Servat
 * @since 11 apr. 2007
 */
public class BehaviorSpecificationSection extends PropertyViewSection {

	/**
	 * Buttons used in the section.
	 */
	private Button browseButton, removeButton; 

	/**
	 * Associated label.
	 */
	private CLabel label;

	/**
	 * The parent Composite.
	 */
	private Composite parent;

	/**
	 * Listener for the delete button.
	 */
	protected MouseListener removeButtonListener;

	/**
	 * Listener for the browse button.
	 */
	protected MouseListener browseButtonListener;

	/**
	 * Some references to images used for buttons.
	 */
	private final org.eclipse.swt.graphics.Image remove_img = PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Delete_16x16.gif");
	private final org.eclipse.swt.graphics.Image add_img = PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Add_16x16.gif");

	/**
	 * Creates the section.
	 * 
	 * @param parent the parent Composite.
	 * @param tabbedPropertySheetPage TabbedPropertySheetPage onto which to add the section.
	 */
	@Override
	public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage){
		super.createControls(parent, tabbedPropertySheetPage);

		//a local composite
		Composite composite = getWidgetFactory().createFlatFormComposite(parent);
		this.parent = parent;
		FormData data;

		//label creation
		CLabel cl = getWidgetFactory().createCLabel(composite, "Specif.:"); //$NON-NLS-1$
		cl.setToolTipText("Specification");

		//removeButton layout
		removeButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		removeButton.setImage(remove_img);
		data = new FormData();
		data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
		data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		removeButton.setLayoutData(data);

		//browseButton layout
		browseButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		browseButton.setImage(add_img);
		data = new FormData();
		data.right = new FormAttachment(removeButton, -ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		browseButton.setLayoutData(data);

		//signal label
		label = getWidgetFactory().createCLabel(composite, "", SWT.BORDER);
		data = new FormData();
		data.left = new FormAttachment(0, STANDARD_LABEL_WIDTH);
		data.right = new FormAttachment(browseButton, -ITabbedPropertyConstants.HSPACE);
		data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		label.setLayoutData(data);

		final TabbedPropertySheetPage thePage = tabbedPropertySheetPage;
		
		label.addMouseListener(new MouseListener(){
			public void mouseUp(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
			}

			public void mouseDoubleClick(MouseEvent e) {
				//TODO: find a solution to load a new property page
				if(((Behavior)getElement()).getSpecification() != null){
					BehavioralFeature feat = ((Behavior)getElement()).getSpecification();
					EditPart selection = null;
					
					Iterator<EditPart> i = LookForElement.getAllOutlineEditParts().iterator();
					while((selection == null) && i.hasNext()){
						EditPart current = i.next() ;
						if((current.getModel() != null) && current.getModel().equals(feat))
							selection = current ;
					}
					if(selection != null){
						thePage.selectionChanged(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(), new StructuredSelection(selection));
					}
				}

			}

		});

		//listeners setting
		browseButtonListener = new BrowseButtonlistener();
		browseButton.addMouseListener(browseButtonListener);
		removeButtonListener = new RemoveButtonlistener();
		removeButton.addMouseListener(removeButtonListener);
	}

	/**
	 * Refreshes the section.
	 */
	@Override
	public void refresh(){
		if(!browseButton.isDisposed()){
			BehavioralFeature specification = ((Behavior) getElement()).getSpecification();
			if(specification == null){
				if(!label.isDisposed())
					label.setText("Specification Unset");
				if(!removeButton.isDisposed())
					removeButton.setEnabled(false);
			}
			else{
				if(!label.isDisposed())
					if (specification instanceof Operation) {
						label.setText(com.cea.papyrus.umlutils.Operation.getSignature((Operation) specification, true));
					} else {
						label.setText(specification.getQualifiedName());
					}

				if(!removeButton.isDisposed())
					removeButton.setEnabled(true);
			}
		}
	}

	/**
	 * Listener for the RemoveButton.
	 * Specific behavior is implemented in removeButtonPressed.
	 */
	protected class RemoveButtonlistener implements MouseListener{

		/**
		 * Does nothing.
		 * @param e MouseEvent.
		 */
		public void mouseDoubleClick(MouseEvent e){
		}

		/**
		 * Does nothing.
		 * @param e MouseEvent.
		 */
		public void mouseDown(MouseEvent e){
		}

		/**
		 * Calls the removeButtonPressed() which does the job then refresh().
		 * @param e MouseEvent.
		 */
		public void mouseUp(MouseEvent e){
			removeButtonPressed();
			refresh();
		}
	}

	/**
	 * Listener for the BrowseButton.
	 * Specific behavior is implemented in browseButtonPressed.
	 */
	protected class BrowseButtonlistener implements MouseListener{

		/**
		 * Does nothing.
		 * @param e MouseEvent.
		 */
		public void mouseDoubleClick(MouseEvent e){
		}

		/**
		 * Does nothing.
		 * @param e MouseEvent.
		 */
		public void mouseDown(MouseEvent e){
		}

		/**
		 * Calls the browseButtonPressed() which does the job then refresh().
		 * @param e MouseEvent.
		 */
		public void mouseUp(MouseEvent e){
			browseButtonPressed();
			refresh();
		}
	}

	/**
	 * Behavior executed when remove button is pressed.
	 */
	protected void removeButtonPressed(){
		((Behavior) getElement()).setSpecification(null);
	}

	/**
	 * Behavior executed when browse button is pressed.
	 */
	protected void browseButtonPressed(){

		Behavior behavior = (Behavior) getElement();
		BehavioredClassifier treeRoot = behavior.getContext();

		if (treeRoot instanceof StateMachine) {
			StateMachine statemachine = (StateMachine) treeRoot;			
			treeRoot = statemachine.getContext();
		}

		OperationTreeSelectionDialog dialog = new OperationTreeSelectionDialog(parent.getShell(), treeRoot);
		int result = dialog.open();
		if(result == IDialogConstants.OK_ID){
			Operation operation = dialog.getResult(); 
			if(operation != null) {
				((Behavior)getElement()).setSpecification(operation);
			}
		}
	}

	/**
	 * Disposes of the buttons and listeners. 
	 */
	public void dispose(){
		super.dispose();
		if((removeButton != null) && !removeButton.isDisposed())
			removeButton.removeMouseListener(removeButtonListener);
		if((browseButton != null) && !browseButton.isDisposed())
			browseButton.removeMouseListener(browseButtonListener);
	}
}


